#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>
#include "aimage.h"
#include "aimage_utils.h"
#include "aimage_ppm.h"

int main( int argc, const char *argv[] )
{
	AIMAGE i0;
	AIMAGE histogram;
	int iindex;
	int zerocount = 0;
	
	float hr[ 1000 ];
	float hg[ 1000 ];
	float hb[ 1000 ];
	float hi[ 1000 ];

	const char *file = "stdin";
	if ( argc >=2 ) 
	{
		file = argv[1];
	}

	bool compress = false;
	assert( argc == 3 );
	{
		compress = true;
	}

	fprintf(stderr, "Loading %s\n", file );
	AIMAGE_PPM_UTILS::load(i0, file );

	for ( iindex = 0; iindex < 1000; ++iindex )
	{
		hr[ iindex ] = 0.0f;
		hg[ iindex ] = 0.0f;
		hb[ iindex ] = 0.0f;
		hi[ iindex ] = 0.0f;
	}

	AIMAGE::const_iterator cur, end;

	cur = i0.const_begin();
	end = i0.const_end();
	float samples = 0;

	while ( cur != end )
	{
		APIXEL p;
		p = *cur;

		if ( p.r == 0 && p.g == 0 && p.b == 0 )
		{
			zerocount++;
		}

		int ir = p.r * 1000 / FULL_INT;
		if ( ir >= 1000 ) ir = 999;
		assert ( ir >= 0 && ir < 1000 );
		
		int ig = p.g * 1000 / FULL_INT;
		if ( ig >= 1000 ) ig = 999;
		assert ( ig >= 0 && ig < 1000 );
		
		int ib = p.b * 1000 / FULL_INT;
		if ( ib >= 1000 ) ib = 999;
		assert ( ib >= 0 && ib < 1000 );
		
		int ii = ( p.r * 3 + p.g * 6 + p.b ) / 10;
		ii = ii * 1000 / FULL_INT;
		if ( ii >= 1000 ) ii = 999;
		assert ( ii >= 0 && ii < 1000 );

		hr[ ir ]++;
		hg[ ig ]++;
		hb[ ib ]++;
		hi[ ii ]++;
		samples++;
		++cur;
	}

	fprintf(stderr, "%g%% samples were 0\n", 
		((float) zerocount ) / ((float) samples ) * 100.0f );

	for ( iindex = 0; iindex < 1000; ++iindex )
	{
		hr[ iindex ] /= samples;
		hg[ iindex ] /= samples;
		hb[ iindex ] /= samples;
		hi[ iindex ] /= samples;
	}
	if ( compress )
	{
		for ( iindex = 0; iindex < 1000; iindex+=4 )
		{
			hr[iindex]=max(hr[iindex],(max(hr[iindex+1],max(hr[iindex+2],hr[iindex+3]))));
			hg[iindex]=max(hg[iindex],(max(hg[iindex+1],max(hg[iindex+2],hg[iindex+3]))));
			hb[iindex]=max(hb[iindex],(max(hb[iindex+1],max(hb[iindex+2],hb[iindex+3]))));
			hi[iindex]=max(hi[iindex],(max(hi[iindex+1],max(hi[iindex+2],hi[iindex+3]))));
			hr[iindex+1]=hr[iindex];
			hr[iindex+2]=hr[iindex];
			hr[iindex+3]=hr[iindex];
			hg[iindex+1]=hg[iindex];
			hg[iindex+2]=hg[iindex];
			hg[iindex+3]=hg[iindex];
			hb[iindex+1]=hb[iindex];
			hb[iindex+2]=hb[iindex];
			hb[iindex+3]=hb[iindex];
			hi[iindex+1]=hi[iindex];
			hi[iindex+2]=hi[iindex];
			hi[iindex+3]=hi[iindex];
		}
	}

	
	histogram.alloc_image( 1200, 1200 );
	AIU::cls( histogram, 0, 0, 0 );

	float *csamples[4]= { hr, hg, hb, hi };

	APIXEL colours[ 4 ];
	colours[ 0 ] = APIXEL( 1.0, 0.0, 0.0 );
	colours[ 1 ] = APIXEL( 0.0, 1.0, 0.0 );
	colours[ 2 ] = APIXEL( 0.0, 0.0, 1.0 );
	colours[ 3 ] = APIXEL( 1.0, 1.0, 1.0 );

	fprintf(stderr, "rendering\n");

	for ( iindex = 0; iindex < 1000; ++iindex )
	{
		for ( int sample = 0; sample < 4; ++sample )
		{
			int x = iindex + 100;
			int y = (sample +1)* 266 + 50;
			float logval = csamples[ sample ][ iindex ];
			logval = logval * M_E * M_E * M_E * M_E * M_E * M_E * M_E * M_E * M_E;
			if ( logval < M_E )
				continue;
			logval = ( logf( logval ) - 1.0f ) / 8.0f;
			if ( logval < 0 || logval > 1 )
			{
				fprintf(stderr,"out of bounds %g %g\n", logval, csamples[ sample ][ iindex ]);
			}
			assert( logval >= 0 && logval <= 1 );
			int y_top = y - (int) ( logval * 250 );
			histogram.line( x, y, x, y_top, colours[sample] );
		}
	}

	APIXEL grey = APIXEL( 0.5, 0.5, 0.5 );
	
	for ( int i = 0 ; i < 4; ++i )
	{
		int x0 = 100;
		int x1 = 100 + 1000;
		int y1 = (i+1) * 266 + 50;
		int y0 = y1 - 250;

		histogram.line( x0, y0, x1, y0, grey );
		histogram.line( x0, y1, x1, y1, grey );
		histogram.line( x0, y0, x0, y1, grey );
		histogram.line( x1, y0, x1, y1, grey );
	}


	AIMAGE_PPM_UTILS::save( histogram, "stdout", true );

}

